package com.paradogs.framework.core.netty.server;

import com.paradogs.framework.core.events.ServerStartEvent;
import com.paradogs.framework.core.utils.EventUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * @author: yumi
 * @date: 2023/8/26  17:19
 * @Description: TODO
 */
@Slf4j
@Component
public class PRServerLaunch implements ApplicationRunner {

    private ServerBootstrap server;

    private NioEventLoopGroup boss;

    private NioEventLoopGroup worker;

    private Channel channel;

    @Autowired
    private ServerProperties properties;

    @Autowired
    private PRServerChannelInitializer channelInitializer;

    /**
     * 启动 netty 服务器
     */
    public void start() {

        // eventLoop
        boss = new NioEventLoopGroup();
        worker = new NioEventLoopGroup();

        try {
            // sever
            server = new ServerBootstrap()
                    .group(boss, worker)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(channelInitializer);

            // connect
            channel = server.bind(properties.getPort()).sync().channel();
            channel.closeFuture().addListener(future -> { log.info("Server stop: [{}]", this.properties.getKey()); });

            // start success
            EventUtils.publishEvent(new ServerStartEvent());
            log.info("Server start success: [{} localhost:{}]", properties.getKey(), properties.getPort());

        } catch (InterruptedException e) {
            log.error("Server error：[{}]", e.getMessage(), e);
            this.closeSync();
        }

    }

    /**
     * 同步关闭连接
     * ***ps: 关闭后进度未结束是因为消息处理队列还开着未关闭
     * @return
     */
    public boolean closeSync() {
        try {
            if (this.channel.isOpen()) {
                channel.close().sync();
            }
            if (!worker.isShutdown()) {
                worker.shutdownGracefully();
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        this.start();
    }

}
